package com.itheima.book.manager.dao;

import com.itheima.book.manager.domain.Book;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 * 使用文件存储图书信息的Dao
 */
public class BookFileDao implements BaseBookDao {

    // 定义图书信息存储文件路径的常量
    private static final String BOOK_INFO_PATH = "itheima-book-manager\\bookInfo.txt" ;

    // 定义日期模板的字符串常量
    private static final String DATE_PATTERN = "yyyy-MM-dd" ;

    @Override
    public void deleteByBookId(String bookId) {

        /**
         * 思路：
         * 1. 获取所有的图书信息，可以调用getAllBooks()方法进行获取，得到的就是一个Book数组
         * 2. 根据我们的bookId从数据中查找要删除的图书对应的索引
         * 3. 遍历数组获取每一个Book对象，然后使用当前所遍历的Book对象的bookId和要删除的bookId进行比对，如果相同，就记录这个索引
         * 4. 根据索引删除图书
         * 5. 把数组中的图书信息从新写入到文件中
         */
        // 1. 获取所有的图书信息，可以调用getAllBooks()方法进行获取，得到的就是一个Book数组
        Book[] allBooks = getAllBooks();

        // 2. 根据我们的bookId从数据中查找要删除的图书对应的索引
        int index = -1 ;                                 // 记录要删除的图书对应的索引
        for(int x = 0 ;  x < allBooks.length ; x++) {
            Book bookInArr = allBooks[x] ;
            if(bookInArr != null) {
                if(bookInArr.getBookId().equals(bookId)) {
                    index = x ;
                    break;
                }
            }
        }

        // 3. 根据索引删除图书
        if(index != -1) {
            allBooks[index] = null ;
        }

        // 创建BufferedWriter对象
        BufferedWriter bufferedWriter = null ;
        try {

            // 把数组中的图书信息从新写入到文件中
            bufferedWriter = new BufferedWriter(new FileWriter(BOOK_INFO_PATH)) ;
            for(Book book : allBooks) {

                if(book != null) {

                    // 把图书的信息拼接成一个字符串
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_PATTERN) ;
                    String format = simpleDateFormat.format(book.getPublishDate());
                    String bookInfo = book.getBookId() + "," + book.getBookName() + "," + format + "," + book.getPrice() ;

                    // 把图书数据写入到文件中
                    bufferedWriter.write(bookInfo);
                    bufferedWriter.newLine();
                    bufferedWriter.flush();

                }

            }

        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(bufferedWriter != null) {
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Override
    public void updateBookByBookId(Book book) {

        /**
         * 思路：
         * 1. 把图书信息从文件中读取出来存储到集合中
         * 2. 根据要修改的图书id从集合中找到对应的索引
         * 3. 进行图书的修改操作
         * 4. 把集合中的数据重新写入到文件中(不要进行追加写)
         */
        // 1. 调用getAllBooks方法获取所有的图书信息
        Book[] allBooks = getAllBooks();

        // 2. 根据要修改的图书id从容器中找到对应的索引
        int index = -1 ;                               // 记录查找到的Book对应的索引
        for(int x = 0 ; x < allBooks.length ; x++) {
            Book bookInArr = allBooks[x] ;
            if(bookInArr != null) {
                if(bookInArr.getBookId().equals(book.getBookId())) {
                    index = x ;
                    break;
                }
            }
        }

        // 3. 进行图书的修改操作
        if(index != -1) {
            allBooks[index] = book ;
        }

        // 把容器中的数据重新写入到文件中(不要进行追加写)
        BufferedWriter bufferedWriter = null ;
        try{

            // 4. 把容器中的数据重新写入到文件中(不要进行追加写)
            bufferedWriter = new BufferedWriter(new FileWriter(BOOK_INFO_PATH)) ;

            // 5. 遍历数组获取每一个元素
            for(int x = 0 ; x < allBooks.length ; x++) {

                Book bookInArr = allBooks[x] ;

                // 2. 把要图书信息拼接成一个字符串
                // 需要把图书的发布时间转换成字符串
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_PATTERN) ;
                String format = simpleDateFormat.format(bookInArr.getPublishDate());
                String bookInfo = bookInArr.getBookId() + "," + bookInArr.getBookName() + "," + format + "," + bookInArr.getPrice() ;

                // 把图书信息写入到文件中
                bufferedWriter.write(bookInfo);
                bufferedWriter.newLine();
                bufferedWriter.flush();

            }

        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(bufferedWriter != null) {
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Override
    public boolean addBook(Book book) {

        /**
         * 思路：就是把我们的图书信息存储到文件中，在写新的图书信息的时候需要进行追加写
         *
         * 1. 创建BufferedWriter对象(进行追加写)
         * 2. 把要添加的图书信息拼接成一个字符串
         * 3. 把新的图书信息写入到文件中
         * 4. 释放资源
         *
         */

        // 创建BufferedWriter对象(进行追加写)
        BufferedWriter bufferedWriter = null ;
        try {

            // 1. 创建BufferedWriter对象(进行追加写)
            bufferedWriter = new BufferedWriter(new FileWriter(BOOK_INFO_PATH, true)) ;

            // 2. 把要添加的图书信息拼接成一个字符串
            // 需要把图书的发布时间转换成字符串
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_PATTERN) ;
            String format = simpleDateFormat.format(book.getPublishDate());
            String bookInfo = book.getBookId() + "," + book.getBookName() + "," + format + "," + book.getPrice() ;

            // 3. 把新的图书信息写入到文件中
            bufferedWriter.write(bookInfo);
            bufferedWriter.newLine();
            bufferedWriter.flush();

            // 4. 返回
            return true ;

        }catch (Exception e) {
            e.printStackTrace();
        } finally {

            if(bufferedWriter != null) {
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        return false;
    }

    /**
     * 查询所有的图书信息
     * @return
     */
    @Override
    public Book[] getAllBooks() {

        /**
         * 我们文件中是一行一个图书信息，而图书的信息(属性)使用","隔开
         * book001,java编程思想,2019-02-12,99.99
         * 读取文件中的数据，将数据封装到Book对象中，而文件中可能会存在多个图书信息，因为我们需要使用多个Book对象进行封装
         * 然后我们需要把多个图书信息存储到一个容器中，那么我们应该选择哪个容器呢？集合
         * 而我们方法需要的返回值是一个数组，因此我们需要将集合转换成数组进行返回操作
         *
         * 步骤：
         * 1. 我们可以把从文件中读取到的数据先存储到ArrayList集合中，因此我们需要创建一个ArrayList集合对象
         * 2. 创建BufferedReader对象
         * 3. 一次读取一行数据，对数据进行解析，把读取到的数据封装到Book对象中，在Book对象添加到ArrayList集合中
         * 4. 释放资源
         * 5. 把ArrayList集合转换成数组进行返回
         */

        // 创建BufferedReader对象
        BufferedReader bufferedReader = null ;

        try {

            // 1. 创建一个ArrayList对象
            ArrayList<Book> bookArrayList = new ArrayList<Book>() ;

            // 为了提高程序的健壮性，把我们的指定文件的路径"itheima-book-manager\\bookInfo.txt"封装成一个File对象
            // 然后判断这个文件是否存在，如果不存在就创建一个文件
            File file = new File(BOOK_INFO_PATH);
            if(!file.exists()) {
                file.createNewFile() ;
            }

            // 2. 创建BufferedReader对象
            bufferedReader = new BufferedReader(new FileReader(BOOK_INFO_PATH)) ;

            // 3. 一次读取一行数据
            String line = null ;            // 作用: 记录读取到的行数据
            while((line = bufferedReader.readLine()) != null) {

                // 对数据进行解析
                // book001,java编程思想,2019-02-12,99.99
                String[] bookInfoArr = line.split(",");
                String bookId = bookInfoArr[0] ;
                String bookName = bookInfoArr[1] ;
                String publishDateStr = bookInfoArr[2] ;
                String priceStr = bookInfoArr[3] ;

                // 把读取到的数据封装到Book对象中
                Book book = new Book() ;
                book.setBookId(bookId);
                book.setBookName(bookName);

                // 把这个publishDateStr字符串转换成Date对象
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_PATTERN) ;
                Date publishDate = simpleDateFormat.parse(publishDateStr);

                // 设置发布时间
                book.setPublishDate(publishDate);

                // 把这个价格字符串转换成double类型
                double price = Double.parseDouble(priceStr);
                book.setPrice(price);

                // 在Book对象添加到ArrayList集合中
                bookArrayList.add(book) ;

            }

            // 把ArrayList集合转换成数组进行返回
            Book[] books = new Book[bookArrayList.size()] ;
            for(int x = 0 ; x < bookArrayList.size() ; x++) {
                Book book = bookArrayList.get(x);
                books[x] = book ;
            }

            // 返回
            return books;

        }catch ( Exception e) {
            e.printStackTrace();
        } finally {

            if(bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        return new Book[0];
    }

}
